import platform
import glob
from subprocess import PIPE, Popen
from functools import wraps
from typing import Callable


def work_logger(log_path):
    def logg_decorator(func: Callable):
        @wraps(func)
        def decorated(*args, **kwargs):
            with open(log_path, 'a+') as logf:
                logf.write(f'**** run {func.__name__}****\r\n')
            rt = func(*args, log_path=log_path, **kwargs)
            with open(log_path, 'a+') as logf:
                logf.write(f'\n\n****Completed****\r\n')
            return rt
        return(decorated)
    return logg_decorator


def run_command_sync(command, log_path=None, bufsize=-1, stdin=None,
                     stdout=PIPE, stderr=PIPE, cwd=None, silent=False) -> int:
    '''Run command and wait for return.

    '''
    args = command.split(' ')
    print(command)
    if log_path is not None:
        with open(log_path, 'a+')as log:
            log.write(f'{command}\n')
        try:
            p = Popen(args, bufsize=-1, stdin=stdin,
                      stdout=stdout, stderr=stderr, cwd=cwd)
            outs, errs = p.communicate()
            outs = outs.decode()
            errs = errs.decode()
            if log_path is not None:
                with open(log_path, 'a+') as log:
                    log.write(f'{outs}\n')
                    log.write(f'{errs}\n')
            if not silent:
                print(outs)
                print(errs)
            return p.returncode
        except Exception as e:
            if log_path is not None:
                with open(log_path, 'a+')as log:
                    log.write(f'{e}\n')
            if not silent:
                print(e)
        return -1


def run_command_async(command, log_path=None, bufsize=-1,
                      stdin=None, stdout=None, stderr=None, cwd=None) -> Popen:
    '''Run command without waiting for return.

    '''
    args = command.split(' ')
    print(command)
    if log_path is not None:
        with open(log_path, 'a+') as log:
            log.write(f'{command}\n')
    p = Popen(args, bufsize=-1, stdin=stdin,
              stdout=stdout, stderr=stderr, cwd=cwd)
    return p


def get_rid():
    '''Get `.Net RID` of current platform.
        '''
    system_type = platform.system().lower()
    if system_type == 'windows':
        os = 'win'
    elif system_type == 'linux':
        release_files = glob.glob('/etc/*release')
        content = ''
        for release_file in release_files:
            with open(release_file, 'r') as f:
                content += f.read().lower()
            if 'alpine' in content:
                os = 'linux-musl'
            else:
                os = 'linux'
    elif system_type == 'darwin':
        os = 'osx'
    else:
        raise f'unsupported OS: {system_type}'
    print(os)
    machine_type = platform.machine().lower()
    if machine_type in ['x86_64', 'amd64']:
        rid = f'{os}-x64'
    elif machine_type in ['aarch64']:
        rid = f'{os}-arm64'
    elif machine_type in ['armv7l']:
        rid = f'{os}-arm'
    else:
        raise f'unsupported machine type: {machine_type}'
    print(rid)
    return rid
